// src/stores/modules/fault.js
import { defineStore } from 'pinia';
import AxiosMethods from '@/utils/AxiosMethods';
import { ElMessage } from 'element-plus';
import { useDeviceStore } from './device'; // 引入 device store，用于获取设备列表名

// 故障状态映射：前端显示名称 <-> 后端整数值，以及 ElTag 类型
const FaultStatusMap = {
  '待处理': { label: '待处理', tagType: 'danger', value: 0 }, // 红色，表示需要关注
  '处理中': { label: '处理中', tagType: 'warning', value: 1 }, // 黄色，表示正在进行
  '已解决': { label: '已解决', tagType: 'success', value: 2 }, // 绿色，表示已完成
  '已关闭': { label: '已关闭', tagType: 'info', value: 3 },    // 灰色，表示已归档
};

// 紧急程度映射（前端显示名称 <-> 标签类型，后端可能直接接受字符串）
const FaultSeverityMap = {
  '低': { label: '低', tagType: 'info' },    // 灰色
  '中': { label: '中', tagType: '' },        // 默认蓝色
  '高': { label: '高', tagType: 'warning' }, // 黄色
  '紧急': { label: '紧急', tagType: 'danger' }, // 红色
};

export const useFaultStore = defineStore('fault', {
  state: () => ({
    faultList: [],           // 故障列表数据
    loading: false,          // 表格或数据加载状态
    total: 0,                // 列表总条数
    searchForm: {            // 搜索表单模型
      deviceId: null,          // 关联设备 ID
      faultType: '',           // 故障类型
      status: '',              // 故障状态字符串
      severity: '',            // 紧急程度字符串
      reporter: '',            // 报告人
      handler: '',             // 处理人
      reportTimeRange: [],     // 日期范围选择器绑定 [开始时间, 结束时间]
      pageNo: 1,               // 当前页码
      pageSize: 10,            // 每页条数
    },
    faultForm: {             // 新增/编辑弹窗表单模型，使用前端命名
      faultId: null,           // 故障ID，新增时为空，更新时有值
      deviceId: null,          // 关联设备ID (对应后端 eqid)
      faultType: '',           // 故障类型
      faultDesc: '',           // 故障描述 (对应后端 faultdiscribe)
      reportTime: '',          // 报告时间 (对应后端 faultdate)
      severity: '中',          // 紧急程度，默认 '中'
      status: '待处理',        // 故障状态，默认 '待处理'
      reporter: '',            // 报告人
      handler: '',             // 处理人
      handleTime: '',          // 处理时间
      solution: '',            // 解决方案
      remark: '',              // 备注
    },
    selectedFaults: [],      // 表格选中项数组
    dialogVisible: false,    // 新增/编辑弹窗显示状态
    isEdit: false,           // 是否为编辑模式 (true) 或新增模式 (false)
    formSubmitting: false,   // 表单提交中的 loading 状态

    // 暴露映射表给组件消费 for ElTag 和 ElSelect options
    FaultStatusMap: FaultStatusMap,
    FaultSeverityMap: FaultSeverityMap,
  }),

  actions: {
    /**
     * 将前端日期时间字符串 (YYYY-MM-DD HH:mm:ss) 或 Date 对象转换为后端期望的 ISO 8601 格式(YYYY-MM-DDTHH:mm:ss)。
     * @param {string|Date|null} dateTimeStr - 前端日期时间字符串或 Date 对象
     * @returns {string|null} ISO 8601 格式日期时间字符串，或 null
     */
    _formatDateTimeToISO(dateTimeStr) {
      if (!dateTimeStr) return null;
      if (dateTimeStr instanceof Date) {
          // Date 对象直接转 ISO 格式，并截取到秒
          return dateTimeStr.toISOString().slice(0, 19); 
      }
      if (typeof dateTimeStr === 'string' && dateTimeStr.length === 19 && dateTimeStr.includes(' ')) {
          // 如果是 "YYYY-MM-DD HH:mm:ss" 格式，转换为 "YYYY-MM-DDTHH:mm:ss"
          return dateTimeStr.replace(' ', 'T');
      }
      // 如果已经是 ISO 格式，确保只保留到秒
      if (typeof dateTimeStr === 'string' && dateTimeStr.includes('T')) {
          return dateTimeStr.slice(0, 19);
      }
      return null; // 其他未知格式返回 null
    },

    /**
     * 将后端返回的 ISO 8601 格式(YYYY-MM-DDTHH:mm:ss) 字符串转换为前端期望的 YYYY-MM-DD HH:mm:ss 格式。
     * @param {string|null} isoString - 后端返回的 ISO 8601 格式日期时间字符串
     * @returns {string|null} YYYY-MM-DD HH:mm:ss 格式日期时间字符串，或 null
     */
    _formatDateTimeFromISO(isoString) {
      if (!isoString) return null;
      if (typeof isoString === 'string' && isoString.includes('T')) {
          return isoString.replace('T', ' ');
      }
      return isoString; // 如果不是 ISO 带有 'T' 的格式，直接返回原值（可能已经是期望的格式或 null）
    },

    /**
     * 将前端数据模型映射到后端接口需要的字段名和格式
     * @param {Object} frontendData - 前端 faultForm 对象
     * @returns {Object} 后端接口期望的数据对象
     */
    _mapFrontendToBackend(frontendData) {
        const backendData = {
            faultid: frontendData.faultId, // 用于 PUT/DELETE 请求的 ID，POST时会移除此字段
            faultdate: this._formatDateTimeToISO(frontendData.reportTime), // 报告时间
            faultdiscribe: frontendData.faultDesc, // 故障描述
            faultstatus: FaultStatusMap[frontendData.status]?.value ?? null, // 故障状态，字符串转整数
            eqid: frontendData.deviceId, // 设备ID

            // 根据接口约定，这些字段可能直接使用与前端相同的名字
            faultType: frontendData.faultType,
            severity: frontendData.severity,
            reporter: frontendData.reporter,
            handler: frontendData.handler,
            handleTime: this._formatDateTimeToISO(frontendData.handleTime), // 处理时间
            solution: frontendData.solution,
            remark: frontendData.remark,
        };

        // 清理空字符串字段为 null，如果后端期望 null 而非空字符串
        for (const key in backendData) {
            if (backendData[key] === '') {
                backendData[key] = null;
            }
        }
        return backendData;
    },

    /**
     * 将后端返回的数据模型映射到前端组件需要的字段名和格式
     * @param {Object} backendData - 后端返回的原始数据对象
     * @returns {Object} 前端组件期望的数据对象
     */
    _mapBackendToFrontend(backendData) {
        if (!backendData) return {};
        const frontendData = {
            faultId: backendData.faultid,
            deviceId: backendData.eqid,
            faultDesc: backendData.faultdiscribe,
            reportTime: this._formatDateTimeFromISO(backendData.faultdate),
            // 从后端整数状态码映射回前端字符串标签
            status: Object.keys(FaultStatusMap).find(key => FaultStatusMap[key].value === backendData.faultstatus) || '未知状态', 
            
            // 假设这些字段存在于后端返回的完整数据中，且命名与前端一致
            faultType: backendData.faultType,
            severity: backendData.severity,
            reporter: backendData.reporter,
            handler: backendData.handler,
            handleTime: this._formatDateTimeFromISO(backendData.handleTime),
            solution: backendData.solution,
            remark: backendData.remark,
        };
        return frontendData;
    },

    /**
     * 获取指定故障状态对应的 ElTag 颜色类型
     * @param {string} status - 故障状态字符串（如 '待处理'）
     * @returns {string} ElTag 颜色类型字符串（'danger', 'warning', 'success', 'info'）
     */
    getFaultStatusTagType(status) {
      return FaultStatusMap[status] ? FaultStatusMap[status].tagType : '';
    },

    /**
     * 获取指定紧急程度对应的 ElTag 颜色类型
     * @param {string} severity - 紧急程度字符串（如 '紧急'）
     * @returns {string} ElTag 颜色类型字符串（'danger', 'warning', 'info' 或空字符串）
     */
    getFaultSeverityTagType(severity) {
      return FaultSeverityMap[severity] ? FaultSeverityMap[severity].tagType : '';
    },

    /**
     * 获取故障列表数据
     * @param {Object} searchParams - 包含搜索字段和分页信息的参数
     */
    async fetchFaultList(searchParams = {}) {
      this.loading = true;
      try {
        const mergedParams = {
          ...this.searchForm, // 获取 store 中当前的 searchForm 状态
          ...searchParams,    // 外部传入的搜索参数覆盖，优先级更高
        };

        const requestParams = {
          pageNo: mergedParams.pageNo,
          pageSize: mergedParams.pageSize,
          // 将前端 searchForm 中的字段映射到后端期望的字段名
          eqid: mergedParams.deviceId === '' ? null : mergedParams.deviceId,
          faultType: mergedParams.faultType === '' ? null : mergedParams.faultType,
          faultstatus: mergedParams.status === '' ? null : FaultStatusMap[mergedParams.status]?.value ?? null, // 字符串转整数
          severity: mergedParams.severity === '' ? null : mergedParams.severity,
          reporter: mergedParams.reporter === '' ? null : mergedParams.reporter,
          handler: mergedParams.handler === '' ? null : mergedParams.handler,
        };
        
        // 处理日期范围，转换为后端期望的 startTime 和 endTime
        if (mergedParams.reportTimeRange && mergedParams.reportTimeRange.length === 2 && mergedParams.reportTimeRange[0] && mergedParams.reportTimeRange[1]) {
            requestParams.startTime = this._formatDateTimeToISO(mergedParams.reportTimeRange[0]);
            requestParams.endTime = this._formatDateTimeToISO(mergedParams.reportTimeRange[1]);
        } else {
            requestParams.startTime = null;
            requestParams.endTime = null;
        }

        // 添加排序字段，假设后端支持按 faultdate 降序 (新故障在前)
        requestParams.sortBy = 'faultdate'; 
        requestParams.isAsc = false;

        const response = await AxiosMethods.get('/fault', { params: requestParams });

        if (response.data && response.data.code === true) {
          // 接收到后端数据后，转换为前端格式
          let mappedFaults = response.data.data.records.map(fault => this._mapBackendToFrontend(fault));
          this.total = response.data.data.total;

          // 为表格中的 deviceName 字段进行额外处理 (从 deviceStore 获取设备名称)
          const deviceStore = useDeviceStore();
          // 确保 deviceStore 的 deviceList 已经加载
          if (deviceStore.deviceList.length === 0) { 
              await deviceStore.fetchDeviceList({ pageNo: 1, pageSize: 99999 }); // 如果为空，尝试加载所有设备
          }
          const deviceMap = new Map();
          deviceStore.deviceList.forEach(d => deviceMap.set(d.eqid, d.eqname));

          // 将设备名称绑定到故障记录上
          this.faultList = mappedFaults.map(fault => ({
              ...fault,
              deviceName: deviceMap.get(fault.deviceId) || '未知设备' // 如果找不到设备，显示“未知设备”
          }));

          // 返回 실제数据，但 store 状态也已更新
          return this.faultList; 
        } else {
          console.error('API Error: Failed to fetch fault list.', response.data);
          throw new Error(response.data.message || '获取故障列表失败');
        }
      } catch (error) {
        console.error('Network/Client Error: Error fetching fault list:', error);
        ElMessage.error(`获取故障列表失败: ${error.message || '未知错误'}`);
        throw error; // 向上抛出错误以便组件层捕获（如果需要）
      } finally {
        this.loading = false;
      }
    },

    /**
     * 获取单个故障详情
     * @param {number} faultId - 故障ID
     * @returns {Object} 返回前端格式的单个故障对象
     */
    async fetchFaultDetail(faultId) {
      if (!faultId) {
          ElMessage.warning('无效的故障ID，无法获取详情。');
          return null;
      }
      try {
        const response = await AxiosMethods.get(`/fault/${faultId}`); 
        if (response.data && response.data.code === true) {
          const detail = this._mapBackendToFrontend(response.data.data);
          
          // 获取设备名称并添加到详情中
          const deviceStore = useDeviceStore();
          if (deviceStore.deviceList.length === 0) {
              await deviceStore.fetchDeviceList({ pageNo: 1, pageSize: 99999 });
          }
          const device = deviceStore.deviceList.find(d => d.eqid === detail.deviceId);
          detail.deviceName = device ? device.eqname : '未知设备';

          return detail;
        } else {
          console.error(`API Error: Failed to fetch fault detail for ID ${faultId}.`, response.data);
          throw new Error(response.data.message || '获取故障详情失败');
        }
      } catch (error) {
        console.error(`Network/Client Error: Error fetching fault detail for ID ${faultId}:`, error);
        ElMessage.error(`获取故障详情失败: ${error.message || '未知错误'}`);
        throw error;
      }
    },

    /**
     * 新增故障工单
     */
    async addFault() {
      this.formSubmitting = true;
      try {
        const dataToSend = this._mapFrontendToBackend(this.faultForm);
        delete dataToSend.faultid; // 确保新增时不会带上 faultid

        const response = await AxiosMethods.post('/fault', dataToSend);
        if (response.data && response.data.code === true) {
          ElMessage.success('新增故障工单成功！');
          this.dialogVisible = false; // 关闭弹窗
          this.resetFaultForm();      // 重置表单状态
          await this.fetchFaultList(); // 刷新列表，可能需要回到第一页
        } else {
          console.error('API Error: Failed to add fault.', response.data);
          throw new Error(response.data.message || '新增故障工单失败');
        }
      } catch (error) {
        console.error('Network/Client Error: Error adding fault:', error);
        ElMessage.error(`新增故障工单失败: ${error.message || '未知错误'}`);
        throw error;
      } finally {
        this.formSubmitting = false;
      }
    },

    /**
     * 更新故障工单信息
     */
    async updateFault() {
      this.formSubmitting = true;
      try {
        const dataToSend = this._mapFrontendToBackend(this.faultForm);
        const faultIdForPath = dataToSend.faultid; // 从映射后的数据中获取 faultid
        if (faultIdForPath === null || faultIdForPath === undefined) {
             throw new Error('更新故障时，故障ID不能为空。');
        }
        const response = await AxiosMethods.put(`/fault/${faultIdForPath}`, dataToSend);
        if (response.data && response.data.code === true) {
          ElMessage.success('故障工单信息更新成功！');
          this.dialogVisible = false; // 关闭弹窗
          this.resetFaultForm();      // 重置表单状态
          await this.fetchFaultList(); // 刷新列表
        } else {
          console.error(`API Error: Failed to update fault ID ${faultIdForPath}.`, response.data);
          throw new Error(response.data.message || '更新故障工单失败');
        }
      } catch (error) {
        console.error('Network/Client Error: Error updating fault:', error);
        ElMessage.error(`更新故障工单失败: ${error.message || '未知错误'}`);
        throw error;
      } finally {
        this.formSubmitting = false;
      }
    },

    /**
     * 删除单个故障工单
     * @param {number} faultId - 故障工单的ID (前端ID)
     */
    async deleteFault(faultId) { 
      this.formSubmitting = true; // 删除操作也开启 loading
      try {
        const response = await AxiosMethods.delete(`/fault/${faultId}`); 
        if (response.data && response.data.code === true) {
          ElMessage.success(`故障ID "${faultId}" 已成功删除！`);
          // 重新计算当前页，防止删除当前页最后一条数据后页面为空
          const currentPage = this.searchForm.pageNo;
          const totalItemsAfterDelete = this.total - 1;
          const maxPage = Math.max(1, Math.ceil(totalItemsAfterDelete / this.searchForm.pageSize));
          if (currentPage > maxPage) {
              this.searchForm.pageNo = maxPage; // 回到上一页
          }
          await this.fetchFaultList(); // 刷新列表
        } else {
          console.error(`API Error: Failed to delete fault ID ${faultId}.`, response.data);
          throw new Error(response.data.message || `删除故障ID "${faultId}" 失败`);
        }
      } catch (error) {
        console.error('Network/Client Error: Error deleting fault:', error);
        ElMessage.error(`删除故障失败: ${error.message || '未知错误'}`);
        throw error; 
      } finally {
        this.formSubmitting = false;
      }
    },

    /**
     * 批量删除故障工单（通过多次调用单个删除接口实现）
     * @param {Array<number>} faultIds - 要删除的故障ID数组 (前端ID)
     */
    async deleteFaults(faultIds) {
      if (!faultIds || faultIds.length === 0) {
        ElMessage.warning('请选择要删除的故障工单。');
        return;
      }
      this.formSubmitting = true; 

      let successCount = 0;
      const failedFaultIds = [];
      const totalToDelete = faultIds.length;

      try {
        // 使用 Promise.allSettled 等待所有删除请求完成，无论成功或失败
        const deletePromises = faultIds.map(async (faultId) => {
          try {
            const response = await AxiosMethods.delete(`/fault/${faultId}`); 
            if (response.data && response.data.code === true) {
              // 成功时返回 ID 便于统计
              return { status: 'fulfilled', faultId: faultId };
            } else {
              // 失败时抛出错误，会在 .catch 捕获，但 Promise.allSettled 仍认为此 promise 解决
              throw new Error(response.data.message || `删除故障 ${faultId} 失败`);
            }
          } catch (error) {
            // 记录失败的 ID 和原因
            return { status: 'rejected', faultId: faultId, reason: error.message || '未知错误' };
          }
        });

        const results = await Promise.allSettled(deletePromises);

        results.forEach(result => {
          if (result.status === 'fulfilled') {
            successCount++;
          } else {
            failedFaultIds.push(result.reason ? `${result.faultId} (${result.reason})` : result.faultId);
            console.error(`删除故障 ${result.faultId} 失败:`, result.reason);
          }
        });

        // 根据删除结果给出不同提示
        if (successCount === totalToDelete) {
          ElMessage.success(`成功删除了 ${successCount} 个故障工单。`);
        } else if (successCount > 0 && failedFaultIds.length > 0) {
          const failedIdsMsg = failedFaultIds.length > 5 ? failedFaultIds.slice(0, 5).join(', ') + '...等' : failedFaultIds.join(', ');
          ElMessage.warning(`部分故障工单删除成功：成功 ${successCount} 个，失败 ${failedFaultIds.length} 个（详情: ${failedIdsMsg}）。`);
        } else {
          ElMessage.error(`所有选中故障工单删除失败，请检查网络或权限。`);
        }
        
        // 重新计算当前页，如果当前页数据不足，跳转到前一页
        const currentPage = this.searchForm.pageNo;
        const totalItemsAfterDeletion = this.total - successCount; 
        const maxPage = Math.max(1, Math.ceil(totalItemsAfterDeletion / this.searchForm.pageSize));
        if (currentPage > maxPage) {
            this.searchForm.pageNo = maxPage;
        }
        await this.fetchFaultList(); // 强制刷新列表
        this.selectedFaults = []; // 清空选中项

      } catch (error) {
        console.error('批量删除操作发生未知错误:', error);
        ElMessage.error(`批量删除操作失败: ${error.message || '未知错误'}`);
      } finally {
        this.formSubmitting = false;
      }
    },

    // ---- 状态与表单重置 ----

    /**
     * 重置搜索表单到初始状态
     */
    resetSearchForm() {
      this.searchForm = {
        deviceId: null,
        faultType: '',
        status: '',
        severity: '',
        reporter: '',
        handler: '',
        reportTimeRange: [],
        pageNo: 1,
        pageSize: 10,
      };
    },

    /**
     * 重置新增/编辑故障表单到初始状态
     */
    resetFaultForm() {
      this.faultForm = {
        faultId: null,
        deviceId: null,
        faultType: '',
        faultDesc: '',
        reportTime: '',
        severity: '中',
        status: '待处理',
        reporter: '',
        handler: '',
        handleTime: '',
        solution: '',
        remark: '',
      };
    },

    /**
     * 更新选中的故障行数据
     * @param {Array} selected - 选中的行数据数组
     */
    updateSelectedFaults(selected) {
      this.selectedFaults = selected;
    },

    /**
     * 获取故障统计数据 (可用于报表或图表展示)
     * 注意：此方法会拉取大量数据进行本地统计，生产环境建议后端提供聚合接口
     * @param {Object} searchParams - 包含日期范围等搜索参数
     * @returns {Object} 包含统计数据的对象
     */
    async getFaultStatistics(searchParams = {}) {
        try {
            // 设置一个较大的 pageSize 确保获取足够数据进行本地统计
            const allFaults = await this.fetchFaultList({
                ...this.searchForm, 
                ...searchParams,   
                pageNo: 1,
                pageSize: 99999, 
            });
            // fetchFaultList 已经处理了 loading 和错误提示
            return { code: true, data: allFaults, message: '获取故障统计数据成功' };
        } catch (error) {
            console.error('Error fetching data for fault statistics:', error);
            // 错误信息已由 fetchFaultList 提示，这里可抛出简洁信息
            throw { code: false, message: error.message || '获取统计原始数据异常' };
        }
    },
  },
});
